package rsi.mesoscopic.math;

import java.awt.geom.Line2D;
import java.awt.geom.Point2D;

public final class Geom {
	
	public static double getDistance(int x1, int y1, int x2, int y2) {
		return Math.sqrt(Math.pow(x1-x2, 2) + Math.pow(y1-y2, 2));
	}
	
	public static double getAngle(int x1, int y1, int x2, int y2) {
		
		double coefAng = Geom.getCoefAngular(x1, y1, x2, y2);
		
		return Math.atan(coefAng) + (x2 < x1 ? Math.PI : 0);
	}
	
	public static double calculaX(double coefA, double coefLinear, double novoY) {
		double x = ((float) (novoY - coefLinear)) / coefA;
		
		return x;
	}
	
	public static double calculaY(double coefA, double coefLinear, double novoX) {
		double y = coefA * novoX + coefLinear;
		
		return y;
	}
	
	public static double calculaX(double x1, double x2, double y1, double y2, double novoY) {
		double a = getCoefAngular(x1, y1, x2, y2);
		double b = getCoefLinear(x1, y1, x2, y2);
		double x = ((float) (novoY - b)) / a;

		return x;
	}

	public static int calculaY(double x1, double x2, double y1, double y2, double novoX) {
		double a = getCoefAngular(x1, y1, x2, y2);
		double b = getCoefLinear(x1, y1, x2, y2);
		double y = a * novoX + b;

		return (int) y;
	}
	
	public static double getCoefAngular(double x1, double y1, double x2, double y2) {
		return (y2 - y1) / (x2 - x1);
	}
	
	public static float getCoefLinear(double x1, double y1, double x2, double y2) {
		
		if(x1 == 0) {
			return (float) y1;
		}
		
		float fx1 = (float) x1;
		float fy1 = (float) y1;
		float fx2 = (float) x2;
		float fy2 = (float) y2;
		return (fy2 - fy1*fx2/fx1)/(1 - fx2/fx1);
	}
	
	public static Point2D.Double intersection(Line2D.Double l1, Line2D.Double l2) {
	
		Point2D.Double point = new Point2D.Double(0, 0);
		
		Point2D l1p1 = l1.getP1();
		Point2D l1p2 = l1.getP2();
		Point2D l2p1 = l2.getP1();
		Point2D l2p2 = l2.getP2();
		
		double a1 = getCoefAngular(l1p1.getX(), l1p1.getY(), l1p2.getX(), l1p2.getY());
		double a2 = getCoefAngular(l2p1.getX(), l2p1.getY(), l2p2.getX(), l2p2.getY());
		double b1 = getCoefLinear(l1p1.getX(), l1p1.getY(), l1p2.getX(), l1p2.getY());
		double b2 = getCoefLinear(l2p1.getX(), l2p1.getY(), l2p2.getX(), l2p2.getY());
		
		if(a1 == a2) {
			return null;
		}
		
		int xIntersection = (int)((b1-b2)/(a2-a1));
		int yIntersection = (int)((b2 -(b1*a2)/a1)/(1-a2/a1));
		
		point.x = xIntersection;
		point.y = yIntersection;
		
		return point;
	}
	
	public static Point2D verticalLineIntersection(Point2D p1, Point2D p2, int x) {
		Point2D.Double point = new Point2D.Double(x, 0);
		
		if(p1.getY() == p2.getY()) {
			//teta = 0
			point.x = p1.getY();
		}else {
			point.y = (calculaY(p1.getX(), p2.getX(), p1.getY(), p2.getY(), x));
		}
		
		return point;
	}
	
	public static Point2D horizontallLineIntersection(Point2D p1, Point2D p2, int y) {
		Point2D.Double point = new Point2D.Double(0, y);
		
		if(p1.getX() == p2.getX()) {
			point.x = (p1.getX());
		}else {
			point.y = (calculaX(p1.getX(), p2.getX(), p1.getY(), p2.getY(), y));
		}
		
		return point;
	}
	
	public static boolean lineIntersects(Point2D p1, Point2D p2, Point2D p, double error) {
		return lineIntersects(
				p1.getX(), p1.getY(), p2.getX(), p2.getY(), p.getX(), p.getY(), error);
	}
	
	public static boolean lineIntersects(double x1, double y1, double x2, double y2, double x, double y, double error) {
		
		if(Math.abs(x1-x2) < Math.abs(y1-y2)) {
			return lineIntersects(y1, x1, y2, x2, y, x, error);
		}
		
		double xMax = Math.max(x1, x2);
		double xMin = Math.min(x1, x2);
		
		double coefAng = (double)(y2 - y1)/(double)(x2 - x1);
		double coefLin = ((double)y1) - coefAng*((double)x1);
		
		if(x >= xMin - error && x <= xMax + error) {
			double py   = coefAng * (double)x + coefLin;
			double yMax = py + error; 
			double yMin = py - error;
			
			if(y >= yMin && y <= yMax){
				return true;
			}
		}

		return false;
	}

	public static void main(String args[]) {
		Point2D p1 = new Point2D.Double(0, 2);
		Point2D p2 = new Point2D.Double(8, 2);
		
		Point2D intersection = Geom.verticalLineIntersection(p1, p2, 4);
		
		System.out.printf("(x=%f, y=%f)", intersection.getX(), intersection.getY());
	}
}
